﻿using System;
using SNSGame.Net;

namespace SNSGame.SNSGame
{
    /// <summary>
    /// 游戏应用接口基类
    /// zhouyu,2011-08-13 created.
    /// zhouyu,2011-12-23 modify ApiBase的第二版本，Url可以有参数
    /// </summary>
    public abstract class AppApiBase
    {
        private static AppConfigBase _appConfig;

        /// <summary>
        /// 应用配置信息
        /// </summary>
        protected AppConfigBase AppConfig
        {
            get { return _appConfig; }
            set { _appConfig = value; }
        }

        /// <summary>
        /// 时间戳,不满意自已重写吧
        /// </summary>
        protected virtual long TimeStamp
        {
            get { return DateTime.Now.Ticks; }
        }

        /// <summary>
        /// 授权基础参数集合
        /// 会自动加入到请求的参数集合中，注意：必须为实例不可为null
        /// Note:该参数可能会加至Url中也可能会加至Post中，所以具体内容由子类决定.
        /// </summary>
        protected abstract HttpParams AuthParamters { get; }


        /// <summary>
        /// 附加于Url上的参数集合
        /// </summary>
        protected virtual HttpParams UrlParamters
        {
            get { return new HttpParams(); }
        }

        /// <summary>
        /// 附加于Post的Form集合中的参数集合，默认是空的参数集合
        /// </summary>
        protected virtual HttpParams PostParamters
        {
            get { return new HttpParams(); }
        }

        /// <summary>
        /// 在原参数基础上附加上参数签名，必须有子类实现。父类不管参数的样子及签名算法的实现。
        /// Note:1. 未对签名参数进行判断，因此不要传入了同名的签名参数。
        /// Note:2. 隐含的一个AuthParamters参数是没有明确传入的，但如果有需要，则必须在子类中处理。
        /// </summary>
        /// <param name="urlParams">待加密的Url参数集合<see cref="HttpParams"/></param>
        /// <param name="postParams">待加密的Post参数集合<see cref="HttpParams"/></param>
        /// <returns></returns>
        protected abstract void AppendSignature(HttpParams urlParams,HttpParams postParams);


        //protected abstract void SwapAccessToken();
       


        #region 同步Http方法

        #region HttpGet方法

        /// <summary>
        /// Http的Get方法实现
        /// </summary>
        /// <param name="uri">请求的URL</param>
        /// <returns>请求结果</returns>
        protected virtual string HttpGet(string uri)
        {
            return HttpGet(uri, null, AppConfig.Timeout);
        }

        /// <summary>
        /// Http的Get方法实现
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="timeout">超时，耗秒</param>
        /// <returns></returns>
        protected virtual string HttpGet(string uri, int timeout)
        {
            return HttpGet(uri, null, timeout);
        }

        /// <summary>
        /// Http的Get方法实现
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="urlParams"></param>
        /// <returns></returns>
        protected virtual string HttpGet(string uri, HttpParams urlParams)
        {
            return HttpGet(uri, urlParams, AppConfig.Timeout);
        }

        /// <summary>
        /// Http的Get方法实现
        /// </summary>
        /// <param name="uri">基础Uri,即?号前的URL部分</param>
        /// <param name="urlParams">附加参数</param>
        /// <param name="timeout">超时时间，耗秒</param>
        /// <returns>请求结果</returns>
        protected virtual string HttpGet(string uri, HttpParams urlParams, int timeout)
        {
            if (string.IsNullOrEmpty(uri) || uri.IndexOf("?") >= 0)
                throw new ArgumentException("uri参数值只能为Url中?号以前的部分。", "uri");

            var urlPms = UrlParamters;
            if (urlParams != null)
                urlPms.AddRange(urlParams);
            AppendSignature(urlPms,null);
            var url = string.Format("{0}?{1}", uri, urlPms);
            var rst = HttpHelper.Get(url, timeout);
            return rst;
        }

        #endregion

        #region HttpPost 请求部分

        /// <summary>
        /// Http的Post
        /// </summary>
        /// <param name="uri">基础链接,问号前的URL</param>
        /// <param name="postData">Post体</param>
        /// <returns></returns>
        protected virtual string HttpPost(string uri,  string postData)
        {
            return HttpPost(uri, null, null, postData);
        }

        /// <summary>
        /// Http的Post
        /// </summary>
        /// <param name="uri">基础链接,问号前的URL</param>
        /// <param name="urlParams">Url参数集合，不为空时附加上Url</param>
        /// <returns></returns>
        protected virtual string HttpPost(string uri,HttpParams urlParams)
        {
            return HttpPost(uri, urlParams, null, null, AppConfig.Timeout);
        }

        /// <summary>
        /// Http的Post
        /// </summary>
        /// <param name="uri">基础链接,问号前的URL</param>
        /// <param name="urlParams">Url参数集合，不为空时附加上Url</param>
        /// <param name="postData">Post体</param>
        /// <returns></returns>
        protected virtual string HttpPost(string uri, HttpParams urlParams, string postData)
        {
            return HttpPost(uri, urlParams, null, postData);
        }

        /// <summary>
        /// Http的Post
        /// </summary>
        /// <param name="uri">基础链接,问号前的URL</param>
        /// <param name="urlParams">Url参数集合，不为空时附加上Url</param>
        /// <param name="postParams">Post参数集合</param>
        /// <returns></returns>
        protected virtual string HttpPost(string uri, HttpParams urlParams, HttpParams postParams)
        {
            return HttpPost(uri, urlParams, postParams, null);
        }

        /// <summary>
        /// Http的Post
        /// </summary>
        /// <param name="uri">基础链接,问号前的URL</param>
        /// <param name="urlParams">Url参数集合，不为空时附加上Url</param>
        /// <param name="postParams">Post参数集合</param>
        /// <param name="postData">Post体</param>
        /// <returns></returns>
        protected virtual string HttpPost(string uri, HttpParams urlParams, HttpParams postParams, string postData)
        {
            return HttpPost(uri, urlParams, postParams, postData, AppConfig.Timeout);
        }

        /// <summary>
        /// Http的Post完全实现
        /// Post参数集合与Post体会一同做为PostBody传送
        /// 2011-12-26
        /// </summary>
        /// <param name="uri">基础链接,问号前的URL</param>
        /// <param name="urlParams">Url参数集合，不为空时附加上Url</param>
        /// <param name="postParams">Post参数集合</param>
        /// <param name="postData">Post体</param>
        /// <param name="timeout">超时时间,ms</param>
        /// <returns></returns>
        protected virtual string HttpPost(string uri, HttpParams urlParams, HttpParams postParams, string postData,int timeout)
        {
            if (string.IsNullOrEmpty(uri) || uri.IndexOf("?") >= 0)
                throw new ArgumentException("uri参数值只能为Url中?号以前的部分。", "uri");

            var urlPms = UrlParamters;
            var postPms = PostParamters;
            if (urlParams != null)
                urlPms.AddRange(urlParams);
            if (postParams != null)
                postPms.AddRange(postParams);

            var postBody = string.Concat(postPms.ToString(), postData ?? string.Empty);
            AppendSignature(urlParams,postParams);//Note:加密设定由子类处理参数
            var rst = HttpHelper.Post(string.Format("{0}?{1}", uri, urlPms), postBody, timeout);
            return rst;
        }

        #endregion

        #endregion



        #region  异步Async Http方法

        /// <summary>
        /// 异步Get方法
        /// </summary>
        /// <param name="uri">Uri</param>
        /// <param name="callback">回调</param>
        /// <returns></returns>
        protected virtual bool AsyncHttpGet(string uri, AsyncHttpCallback callback)
        {
            return AsyncHttpGet(uri, null, callback);
        }

        /// <summary>
        /// 异步Get方法
        /// </summary>
        /// <param name="uri">Uri</param>
        /// <param name="urlParams">Url参数集合</param>
        /// <param name="callback">回调</param>
        /// <returns></returns>
        protected virtual bool AsyncHttpGet(string uri, HttpParams urlParams, AsyncHttpCallback callback)
        {
            if (string.IsNullOrEmpty(uri) || uri.IndexOf("?") >= 0)
                throw new ArgumentException("uri参数值只能为Url中?号以前的部分。", "uri");

            var urlPms = UrlParamters;
            if (urlParams != null)
                urlPms.AddRange(urlParams);
            AppendSignature(urlPms, null);
            var url = string.Format("{0}?{1}", uri, urlPms);
            var rst = HttpHelper.AsyncGet(url, AppConfig.AsyncTimeout,callback);
            return rst;
        }

        /// <summary>
        /// 异步Post
        /// </summary>
        /// <param name="url">Url</param>
        /// <param name="callback">回调</param>
        /// <returns></returns>
        protected virtual bool AsyncHttpPost(string url, AsyncHttpCallback callback)
        {
            return AsyncHttpPost(url, null,null,null, callback);
        }

        /// <summary>
        /// 异步Post
        /// </summary>
        /// <param name="uri">URI</param>
        /// <param name="urlParams">Url参数集合</param>
        /// <param name="postParams">Post参数集合</param>
        /// <param name="postData">Post数据</param>
        /// <param name="callback">回调</param>
        /// <returns></returns>
        protected virtual bool AsyncHttpPost(string uri, HttpParams urlParams,HttpParams postParams,string postData, AsyncHttpCallback callback)
        {
            if (string.IsNullOrEmpty(uri) || uri.IndexOf("?") >= 0)
                throw new ArgumentException("uri参数值只能为Url中?号以前的部分。", "uri");

            var urlPms = UrlParamters;
            var postPms = PostParamters;
            if (urlParams != null)
                urlPms.AddRange(urlParams);
            if (postParams != null)
                postPms.AddRange(postParams);

            var postBody = string.Concat(postPms.ToString(), postData ?? string.Empty);
            AppendSignature(urlParams, postParams);//Note:加密设定由子类处理参数
            var rst = HttpHelper.AsyncPost(string.Format("{0}?{1}", uri, urlPms), postBody, AppConfig.AsyncTimeout,callback);
            return rst;
        }

        #endregion

    }
}